﻿using System;
using Castle.DynamicProxy;
using log4net;
using NHibernate;
using ZenMoney.Core.Services;
using IInterceptor = Castle.DynamicProxy.IInterceptor;

namespace ZenMoney.Core.Container.Interceptors
{
	public class TransactionalInterceptor : IInterceptor
	{
		public bool RollbackOnly { get; set; }

		public void Intercept(IInvocation invocation)
		{
			var logger = LogManager.GetLogger(invocation.Method.DeclaringType);

			var session = GetCurrentSession(invocation);
			var tx = session.Transaction;
			var isFirst = (tx == null || !tx.IsActive);

			if (isFirst)
				tx = session.BeginTransaction();

			try
			{
				invocation.Proceed();

				if (!isFirst)
					return;

				if (RollbackOnly)
					tx.Rollback();
				else
					tx.Commit();					
			}
			catch(Exception e)
			{
				if (!tx.WasRolledBack)
					tx.Rollback();

				logger.Error(Messages.TransactionError, e);
				throw;
			}
		}

		private static ISession GetCurrentSession(IInvocation invocation)
		{
			var service = (TransactionalService) invocation.InvocationTarget;
			return service.Session;
		}
	}
}
